QT连载1:readyRead()函数,数据分包不完整解决办法 您所在的位置:网站首页 串口发送文件 时间间隔设置 QT连载1:readyRead()函数,数据分包不完整解决办法

QT连载1:readyRead()函数,数据分包不完整解决办法

2023-08-04 04:06| 来源: 网络整理| 查看: 265

一,问题

    网上的小伙伴遇到串口接收的函数一般是下列函数,QT中串口接收函数:

//=============串口定义==============// connect(&mSerial,SIGNAL(readyRead()),this,SLOT(SerialPort_Readyread()));

    此函数存在问题:接收数据后,不定时抛出,也就是说串口中有数据就会执行后面的槽函数,然后用下面函数接收:

void MainWindow::SerialPort_Readyread() { QByteArray recvData = mSerial.readAll(); }

    这样接收到的recvData数据就会分包。网上遇到很多说解决这个问题的,但是最后总是会有问题。前面文章中,我也采用的一种方法就是加报头和报尾。但是这个方法也会出现丢数据的情况,所以之后做了很多实验,怎么规避这种丢包的问题。

二,思路

    程序嘛,就是让修改的,不能按照别人给的来。所以换了一种做法,采用下面的方法。

    1.槽函数不采用串口数据触发

    采用下列函数:

connect(&m_timer_test, &QTimer::timeout, this, &MainWindow::handleTimeout_test); void MainWindow::handleTimeout_test() { nRxAllLength = mSerial.bytesAvailable(); recvDataAD = mSerial.readAll(); m_timer_test.stop(); }

注:其中的定时器为发送指令时启动,延时一定时间后接收。标准的MODBUS协议。

    串口数据采用定时器槽函数接收,先判断接收到数据个数,再将数据放进recvDataAD数组里。对于需要定时接收的场合可能不太适用,但是可以作为一个思路。当然如果底层单片机定时发送一定的数据,需要单片机先给一个指令,之后延时一定时间后接收主要主要数据。

2.测试方法

    采用波特率19200和38400,指令下发取单片机一定的数据,修改定时器时间,测试定时器时间最短多少能接收到全部一帧数据。

     举例:波特率19200,设定取单片机字节数45个,改变时间设定:60ms后执行槽函数。此时采集数量一直稳定在45个。证明给单片机下发取数45个指令后,返回45个,串口完全接收,并可以一次弹出。即:QT串口接收45个byte(uint_8),60ms可以接收到完整的数据包。按照这种思路,减小定时器时间。当定时器时间达到47ms时,接收到的数据不再是稳定的45个,会出现其他个数,说明串口已经不能完整的接收到数据包。所以时间定在48ms。由此此处结论:QT接收45个字节时,至少需要间隔48ms,才能得到完整数据包,当然时间越长约好。

 三,测试结果

    (1) 测试结果如下:

波特率:19200采集数量(单位u8)最小时间(单位ms)4548856412581165107205127285173

    波特率为19200时,QT接收完整数据需要的时间。

     其中:蓝色曲线为采集数量对应最小间隔时间,红色曲线为最小间隔时间在19200波特率下能传输的最大数据量。

    可得出:(1)数据量越大,需要间隔时间越长,并且数据量和间隔时间成线性正比。(2)一定时间间隔内,传输数据与最大传输数据个数比例大概是2:1。

 (2) 测试结果如下:

波特率:38400采集数量(单位u8)最小时间(单位ms)4520853412548165642057828599

    波特率为38400时,QT接收完整数据需要的时间。

      其中:蓝色曲线为采集数量对应最小间隔时间,红色曲线为最小间隔时间在38400波特率下能传输的最大数据量。

    同样可得出:(1)数据量越大,需要间隔时间越长,并且数据量和间隔时间成线性正比。(2)一定时间间隔内,传输数据与最大传输数据个数比例大概是4:1。

     波特率19200和波特率38400不同的地方在于接收最大传输数据比例,相同的时间内,波特率增加一倍,传输数据和最大传输数据量比例减小一倍。

    所以初步得出结论:当波特率增加时,传输一定数据需要的间隔时间是线性减小。

四,结论

    (1)QT串口数据不丢包的方法是:延长一定时间,执行槽函数,取数据。如果是QT下发指令取数据,则需延长一定时间最小时间T后,方可取得发送包的完整数据。如果是单片机固定时间上传数据,则需延长时间2*T后,方可取得发送包的完整数据(无法判断什么时候发送报文,没有办法准确开始定时器,所以只能间隔时间t后,可得到完整数据包)。

    (2)QT串口接收数据量一定情况下,波特率越高越好,需要间隔的时间越短。但是相对于波特率能传输的最大数量来说,利用率是下降的。

    (3)不能一直使用网上说的QT函数,没事就自己改改,或许还能找到解决办法。

五,存在问题

    (1)仅仅使用了两种波特率得出结论,可能对于进一步高的波特率不太实用,但是时间有限,工作之余只能草率得出结论,感兴趣的小伙伴可以试试更高波特率的是不是符合上述结论,如果不一致还请相信告诉下,我再进一步验证。

    (2)底层单片机执行程序需要一定时间,下发指令和回复指令需要时间,已经尽量避免,但是肯定还会有执行时间,延长了QT串口的接收时间。

    (3)电脑执行时间没有考虑,电脑越好,应该QT执行的越快,这个没办法,公司只有一台电脑,没有办法做出结论。电脑速率应该也会影响最终结果。如果小伙伴重复试验,结果相差有点,可以参考这个问题。

六,展望

    以后有时间了,可以做下全波特率的执行时间,给出一张完整的接收时间表,其中包含波特率,数据数量,需要时间参数。如果有小伙伴做出来也给个链接哈,表示衷心感谢!

    注:由于小伙伴需要源代码的时间不同,登录邮箱界面太多麻烦,所以建立了一个订阅号,如果有问题或者需要源码,可添加订阅号,留言后会发送源代码或者有任何问题可留言,将积极解决提出的问题。

 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有